// If this file went wrong, then only god will help you... BTW, I like cartesian coordinate system.

import { Map, ResizeCanvas } from "./map.js";
import { add_event_listener, get_device } from "./utils.js";
import { Car } from "./car.js";

const canvas = document.getElementById( 'canvas1' )
const context = canvas.getContext( '2d' )
const map = new Map( canvas.width, canvas.height )
const device = get_device( canvas )
let hasChecked = false

$( "#check_button" ).on( "click", () => {
    if ( check() ) {
        hasChecked = true
    } else {
        alert( "我知道你很急，但你先别急，再检查一下？" )
    }
} )

$( "#upload_button" ).on( "click", () => {
    if ( !hasChecked ) {
        alert( "我知道你很急，但你先别急，先检测一下！" )
        return
    }
    let desc = prompt( "输入一段描述：" )
    $.ajax( {
        async: false, type: "POST", url: "/data/upload_problem", data: to_json(desc), success: () => {
            alert( "成功！" )
        }, error: () => {
            alert( "失败！" )
        }
    } )
    hasChecked = false
} )

const carTypes = [
    [ 'red', 'x', 2 ], [ 'yellow', 'x', 2 ], [ 'blue', 'x', 3 ], [ 'green', 'y', 2 ], [ 'cyan', 'y', 3 ]
]
let carList = []

let check = () => {
    // TODO: Implement this algorithm. Someone will do this.
    return false
}

let in_range = ( pos, type ) => {
    switch ( type[ 1 ] ) {
        case 'x' :
            return pos[ 0 ] + type[ 2 ] <= 6
        case 'y' :
            return pos[ 1 ] + type[ 2 ] <= 6
    }
}

let is_overlap = ( pos, type ) => {
    // FIXME: We should have a more faster algorithm. Or not? :>
    let is_same = ( a, b ) => {
        return a[ 0 ] === b[ 0 ] && a[ 1 ] === b[ 1 ]
    }
    return carList.filter( ( car ) => {
        if ( type[ 1 ] === 'x' && car.allow_direction === 'x' ) {
            let t = pos[ 0 ] + type[ 2 ] - 1, t1 = car.x + car.length - 1
            if ( pos[ 1 ] === car.y && car.x <= t && t <= t1 ) {
                return false
            }
        } else if ( type[ 1 ] === 'y' && car.allow_direction === 'y' ) {
            let t = pos[ 1 ] + type[ 2 ] - 1, t1 = car.y + car.length - 1
            if ( pos[ 0 ] === car.x && car.y <= t && t <= t1 ) {
                return false
            }
        } else if ( type[ 1 ] === 'x' && car.allow_direction === 'y' ) {
            for ( let i = 0; i < car.length; ++i ) {
                for ( let j = 0; j < type[ 2 ]; ++j ) {
                    if ( is_same( [ car.x, car.y + i ], [ pos[ 0 ] + j, pos[ 1 ] ] ) ) {
                        return false
                    }
                }
            }
        } else if ( type[ 1 ] === 'y' && car.allow_direction === 'x' ) {
            for ( let i = 0; i < car.length; ++i ) {
                for ( let j = 0; j < type[ 2 ]; ++j ) {
                    if ( is_same( [ car.x + i, car.y ], [ pos[ 0 ], pos[ 1 ] + j ] ) ) {
                        return false
                    }
                }
            }
        }

        return true
    } ).length !== carList.length
}

let next_car_index = ( car ) => {
    let ind = carTypes.findIndex( ( tCar ) => {
        return is_same_type( tCar, car )
    } ) + 1

    while ( ind > 0 && ind < carTypes.length ) {
        if ( in_range( [ car.x, car.y ], carTypes[ ind ] ) && !is_overlap( [ car.x, car.y ], carTypes[ ind ] ) ) {
            return ind
        }
        ++ind
    }

    return -1
}

function render() {
    context.clearRect( 0, 0, canvas.width, canvas.height )
    map.DrawMap( context )
    map.DrawCars( context )
}

ResizeCanvas( canvas )
render()

function touch_down() {
    let ind = map.get_touch_on_which_rect( device )
    if ( ind === -1 ) {
        return
    }

    let [ x, y ] = [ parseInt( ind / 6 ), ind % 6 ]
    let carInd = map.get_touch_on_which_car( device )

    if ( carInd !== -1 ) {
        let car = carList.find( ( car, ind ) => {
            return ind === carInd
        } )
        carList = carList.filter( ( car, ind ) => {
            return ind !== carInd
        } )
        let ind = next_car_index( car )
        if ( ind !== -1 ) {
            car.update_type( carTypes[ ind ] )
            carList.push( car )
        }
        map.BuildCarRoundRectangles( carList )
    } else {
        let t = carList.findIndex( ( car ) => {
            return is_same_type( carTypes[ 0 ], car )
        } )
        if ( t === -1 ) {
            if ( in_range( [ x, y ], carTypes[ 0 ] ) && !is_overlap( [ x, y ], carTypes[ 0 ] ) ) {
                carList.push( new Car( x, y, 'red', 'x', 2 ) )
            }
        } else {
            let car = new Car( x, y, 'red', 'x', 2 )
            let ind = next_car_index( car )
            if ( ind !== -1 ) {
                car.update_type( carTypes[ ind ] )
                carList.push( car )
            }
        }
        map.BuildCarRoundRectangles( carList )
    }

    render()
}

function is_same_type( a, b ) {
    return a[ 0 ] === b.color && a[ 1 ] === b.allow_direction && a[ 2 ] === b.length
}

function to_json(desc) {
    let res = []
    let t = carList.filter( ( car ) => {
        return !is_same_type( carTypes[ 0 ], car )
    } )
    let theRedCar = carList.find( ( car ) => {
        return is_same_type( carTypes[ 0 ], car )
    } )

    res.push( {
        length: theRedCar.length,
        position: { x: theRedCar.x, y: theRedCar.y },
        allow_direction: theRedCar.allow_direction
    } )
    t.forEach( ( car ) => {
        res.push( {
            length: car.length, position: { x: car.x, y: car.y }, allow_direction: car.allow_direction
        } )
    } )

    // TODO: the designer name here should be provide as the doc said.
    //                                                ↓↓↓↓
    return JSON.stringify( {'cars': res, 'designer': 'Clay', 'description' : desc} )
}

add_event_listener( canvas, 'down', touch_down )
